(function($) {
    $.magicmap = function() {
        // functions
		this.get_map_center = function (){
			var china = new google.maps.LatLng(35.86166, 104.1954);
			var usa = new google.maps.LatLng(37.09024, -95.7129);
			var japan = new google.maps.LatLng(36.204824, 138.2529);
			
			if (navigator.userLanguage) {
				baseLang = navigator.userLanguage.substring(0,2).toLowerCase();
			} else {
				baseLang = navigator.language.substring(0,2).toLowerCase();
			}
			switch(baseLang)
			{
			  case "en":
				  return usa;
			  case "ja":
				  return japan;
			  case "zh":
				  return china;
			  default:
				  return china;
			}
		};
			
        start_routes_search = function() {
            var query = searchbox.val().replace(/(^\s*)|(\s*$)/g, "");;
            if(query.length <=0)
            {
                return false;
            }
            searchresults.hide();
			searchmsg.html('&nbsp;');
			waiting.show();
            geocoder.geocode({'address':query}, function(results, status){
                if (! results) 
                {
                    searchmsg.html("no response");
                } 
                else 
                {
                    if (status == google.maps.GeocoderStatus.OK) 
                    {
						searchresults.html('');
                        if (results.length == 1)
                        {
                            searchbox.val(results[0].formatted_address);
                            gmap.fitBounds(results[0].geometry.viewport);
                        }
                        else
                        {
							table = $('<table cellspacing="0" cellpadding="0" class="results_table"></table>');
                            for (var i=0; i<results.length; i++) {  
							    tr = $('<tr><td>' + results[i].formatted_address + '</td></tr>');
								tr.click({result: results[i]}, function(event){
									searchbox.val(event.data.result.formatted_address);
									gmap.fitBounds(event.data.result.geometry.viewport);
								});
								table.append(tr);
                            }
							position = searchbox.offset();
                            searchresults.css({ left: position.left + "px",
                                                top: position.top + searchbox.height() +
												    parseInt(searchbox.css("border-top-width")) +
													parseInt(searchbox.css("border-bottom-width")) +
													parseInt(searchbox.css("padding-top")) +
													parseInt(searchbox.css("padding-bottom")) +"px",
                                                });
							searchresults.append(table);					
                            searchresults.show();
                        }
                    }
                    else
                    {
                        searchmsg.html("wrong address");
                    }
                }
				waiting.hide();
            });
        };
        
        var markers = [];
        var waypoints = [];
        var origin = null; 
        var destination = null;
        var unit=null;
        var elevation_chart=null;
        var mousemarker = null;
        
        add_marker = function(latlng, icon) {
             markers.push(new google.maps.Marker({
                  position: latlng, 
                  map: gmap,
                  icon: icon
                }));    
        };
        clear_marks = function() {
            for (var i = 0; i < markers.length; i++) {
                markers[i].setMap(null);
            }
        };
        clear_waypoints = function() {
            markers = [];
            origin = null;
            destination = null;
            waypoints = [];
        };
        get_unit = function() {
            return (unit && (unit.val() == 'metric')) ?
                google.maps.DirectionsUnitSystem.METRIC :
                google.maps.DirectionsUnitSystem.IMPERIAL; 
        };
        get_directions = function() {
            if (markers.length<2) {
                return;  
            }
            var request = {
                origin: origin,
                destination: destination,
                waypoints: waypoints,
                travelMode: google.maps.DirectionsTravelMode.DRIVING,
                optimizeWaypoints: false,
                avoidHighways: true,
                avoidTolls: false,
                unitSystem: get_unit(),
            };
            waiting.show();
            searchmsg.html("");
            directionsService.route(request, function(response, status) {
                if (status == google.maps.DirectionsStatus.OK) {
                    directionsDisplay.setDirections(response);
                    clear_marks();
                    show_elevations(response);
                } else {
                    searchmsg.html("no way");
                }
                waiting.hide();
            });
        };
        show_elevations = function(directionsresult) {
            if (elevation_chart) {
                var total_distance = 0;
                route = directionsresult.routes[0];
                for (var i = 0; i < route.legs.length; i++) {
                    total_distance += route.legs[i].distance.value;
                }
                elevationService.getElevationAlongPath({
                  path: route.overview_path,
                  samples: 500
                }, function(elevations){
                       alert(total_distance);
                       var path = [];
                       var data = new google.visualization.DataTable();
                       data.addColumn('string', 'distance');
                       data.addColumn('number', 'Elevation');
                       data.addRows(elevations.length);
                       for (var i = 0; i < elevations.length; i++) {
                           data.setValue(i, 0, (total_distance/elevations.length*(i+1)/1000).toFixed(1)+'');
                           data.setValue(i, 1, Number(elevations[i].elevation.toFixed(6)));
                           path.push(elevations[i].location);
                       }
                       chart = new google.visualization.ColumnChart(elevation_chart[0]);
                       chart.draw(data, {
                          height: 400,
                          legend: 'none',
                          focusBorderColor: '#00ff00',
                          titleX: 'distance (km)',
                          titleY: 'elevation (m)',
                       });
                       google.visualization.events.addListener(chart, 'onmouseover', function(e) {
                          if (mousemarker == null) {
                            mousemarker = new google.maps.Marker({
                              position: elevations[e.row].location,
                              map: gmap,
                              icon: "http://maps.google.cn/mapfiles/ms/icons/green-dot.png"
                            });
                          } else {
                              mousemarker.setPosition(elevations[e.row].location);
                          }
                      });
                      elevation_chart.mouseout(function(){
                          if (mousemarker != null) {
                              mousemarker.setMap(null);
                              mousemarker = null;
                          }
                      });
                });
            }
        };
            
        this.enable_directions = function(options, panel) {
            var ddoptions = options;
            var ddpanel = panel;
            
            directionsService = new google.maps.DirectionsService();
            
            directionsDisplay = new google.maps.DirectionsRenderer(options);
            directionsDisplay.setMap(gmap);
            directionsDisplay.setPanel(panel);  
            
            var resetdiv = document.createElement('input'); 
            resetdiv.type = 'button';  
            resetdiv.style.margin = '4px 0 0 0';
            resetdiv.style.height = '23px';
            resetdiv.value = 'Reset';
            google.maps.event.addDomListener(resetdiv, 'click', function() {
                searchmsg.html("");
                clear_marks();
                clear_waypoints();
                directionsDisplay.setMap(null);
                directionsDisplay.setPanel(null);
                directionsDisplay = new google.maps.DirectionsRenderer(ddoptions);
                directionsDisplay.setMap(gmap);
                directionsDisplay.setPanel(ddpanel);  
            });
            gmap.controls[google.maps.ControlPosition.TOP_RIGHT].push(resetdiv);
            
            unit = $('<select id="unit-input">'+
                         '<option value="imperial">Imperial</option>'+
                         '<option selected="selected" value="metric">Metric</option></select>');
            $(document).append(unit);
            google.maps.event.addDomListener(unit[0], 'change', function() {
                get_directions();
            });
            gmap.controls[google.maps.ControlPosition.RIGHT_TOP].push(unit[0]);

            
            google.maps.event.addListener(gmap, 'click', function(event) {
              if (origin == null) {
                  origin = event.latLng;
                  add_marker(origin,
                    "http://maps.google.cn/mapfiles/marker" + String.fromCharCode(markers.length + 65) + ".png");
              } else if (destination == null) {
                  destination = event.latLng;
                  add_marker(destination,
                    "http://maps.google.cn/mapfiles/marker" + String.fromCharCode(markers.length + 65) + ".png");
              } else {
                  if (waypoints.length < 9) {
                      waypoints.push({ location: destination, stopover: true });
                      destination = event.latLng;
                      add_marker(destination,
                        "http://maps.google.cn/mapfiles/marker" + String.fromCharCode(markers.length + 65) + ".png");
                  } else {
                      alert("Maximum number of waypoints reached");
                      return;
                  }   
              } 
              get_directions();
            });
        };
        
        //init function
        this.initmap = function(options) {
            this.options = {};
            $.extend(this.options, this.defaults, options);

            //init
            var gmap_option = {
                zoom: this.options.zoom,
                mapTypeId: this.options.mapTypeId,
                center: this.options.startcenter,
            }
            map_container = $(this.options.map_container);
            searchbox = $(this.options.searchbox);
            searchbtn = $(this.options.searchbtn);
			waiting = $(this.options.waiting);
            searchresults = $(this.options.searchresults);
			searchmsg = $(this.options.searchmsg);
            
            gmap = new google.maps.Map(map_container[0], gmap_option);
            geocoder = new google.maps.Geocoder();
            
            
            
            if (this.options.elevation_chart)
            {
                elevation_chart = $(this.options.elevation_chart);
                elevationService = new google.maps.ElevationService();
            }
            
            // event handlers
            searchbox.keyup(function(event) {
                if (event.keyCode == '13') 
                {
                    start_routes_search();
                }
            });
            searchbtn.click(function() {
                start_routes_search();
            });
            searchresults.hover(
                function(){$(this).show();},
                function(){$(this).hide();}
            );
            return this;
        };
		
    };
    $.magicmap.prototype={
        name:"magicmap",
        author:"gully chen",
        version:"1.0",

        defaults:{
            map_container: "#routes_map_container",
            searchbox: "#routes_search_query",
            searchbtn: "#routes_search_btn",
			waiting: "#routes_search_waiting",
            searchresults: "#routes_search_results",
			searchmsg: "#routes_search_msg",
            startcenter: new google.maps.LatLng(31.6, 120.34),
            mapTypeId: google.maps.MapTypeId.ROADMAP,
            zoom: 11,
        },
        
        // properties
        map_container: null,
        searchbox: null,
        searchbtn: null,
		waiting:null,
        searchresults: null,
		searchmsg:null,
		
        gmap: null,
        geocoder: null,
        elevationService: null,
    };
})(jQuery);